#include "ClientSocket.h"
#include "SocketException.h"
#include <iostream>
#include <string>
#include <vector>

#define SEPARADOR "."

std::vector<std::string> split(const std::string str,std::string sep=" ")
{
	unsigned posI,posF;
	std::vector<std::string> res;
	
	posI = 0;
	posF = str.find(sep);
	while (posI != std::string::npos) {
		if (posF != std::string::npos)
			res.push_back(str.substr(posI,posF-posI));
		else {
			res.push_back(str.substr(posI,str.size()-posI));
			break;
		}
		posI = posF+1;
		posF = str.find(sep,posI);
	}
	
	return res;	
}

std::string StringToLower(std::string strToConvert)
{
   for(unsigned int i=0;i<strToConvert.length();i++)
      strToConvert[i] = tolower(strToConvert[i]);
      
   return strToConvert;
}


std::string formatoRQuery(std::string arg)
{
	std::string res = "";
	std::vector<std::string> aux;
	std::string signo;
	std::string relev;
	std::string termino;
	unsigned pos;
	
	aux = split(arg);
	for (unsigned i=0;i<aux.size();i++) {
		if (aux[i].size()==1) {
			if ((aux[i]== "+")||(aux[i]== "-")) {
				if ((i+1)<aux.size()) {
					signo = aux[i];
					relev = "1";
					i++;
					termino = aux[i];
					pos = aux[i].find("^");
					if (pos != std::string::npos) {
						relev = aux[i].substr(pos+1,aux[i].size()-pos);
						termino = aux[i].substr(0,pos);						
					}
					res += std::string(SEPARADOR) + termino + std::string(SEPARADOR) + relev + std::string(SEPARADOR) + signo;  					
				}
			}
		}
		else {
			if (aux[i].size()>0) {
					signo = "#";
					relev = "1";
					termino = aux[i];
					pos = aux[i].find("^");
					if (pos != std::string::npos) {
						relev = aux[i].substr(pos+1,aux[i].size()-pos);
						termino = aux[i].substr(0,pos);						
					}
					if ((termino[0] == '+')||(termino[0] == '-')) {
						signo = termino[0];
						termino = termino.substr(1,termino.size()-1); 
					}
					res += std::string(SEPARADOR) + termino + std::string(SEPARADOR) + relev + std::string(SEPARADOR) + signo;
			}
		}
	}
	
	return res;
}


void enviar(std::string str) {
	//std::cout << "enviado: (" << str << ")" << std::endl; 
	try
    	{

      	// IP , puerto destino
      	ClientSocket client_socket ( "localhost", 10000 );

      	std::string reply;

    	try
			{
	  			client_socket << str;
	  			client_socket >> reply;
			}
      	catch ( SocketException& ) {}

      	//std::cout << "Respuesta del servidor:\n\"" << reply << "\"\n";;
            std::cout << reply << std::endl;
        }
  catch ( SocketException& e )
  	  {
    	  std::cout << "Excepcion: " << e.description() << "\n";
      }
}

bool pathValido(std::string path) {
	return true;
}
bool wcQuery(std::string query) {
	if (query.find(' ') == std::string::npos)
		if ((query.find('*') != std::string::npos)||(query.find('?') != std::string::npos))
		   return true;
		else return false;
	else
		return false;
}
bool rankQuery(std::string query) {
	if ((query.find('*') == std::string::npos)&&(query.find('?') == std::string::npos))
	   return true;
	else
	   return false;
}

void procesar(std::string cmd,std::string arg) {
	if (cmd == "st") {
		bool op1,op2 = false;
		if ((op1 = wcQuery(arg)))
			enviar(cmd + "/c" + std::string(SEPARADOR) + arg);
		if ((op2 = rankQuery(arg)))
			enviar(cmd + "/r" + formatoRQuery(arg));
		if ((!op1)&&(!op2))
			std::cout << "Busqueda no valida\n";
	}
	else {
		if (pathValido(arg))
			enviar(cmd + std::string(SEPARADOR) + arg);
		else
			std::cout << "Directorio no valido\n";
	}
	
}

bool catalogoValido(std::string cat) {
	return true;
}

void procesar(std::string cmd,std::string nomcatalogo,std::string query) {
	if (catalogoValido(nomcatalogo)) {
		bool op1,op2 = false;
		if ((op1 = wcQuery(query)))
			enviar(cmd + "/c" + std::string(SEPARADOR) + nomcatalogo + std::string(SEPARADOR) + query);
		if ((op2 = rankQuery(query)))
			enviar(cmd + "/r" + std::string(SEPARADOR) + nomcatalogo + formatoRQuery(query));
		if ((!op1)&&(!op2))
			std::cout << "Busqueda no valida\n";
	}
	else
		std::cout << "Nombre de catalogo no valido\n";	
}  

int main(int argc, char* argv[]) 
{
	std::string cmd,cmd2;
	if (argc < 2)
		std::cout << "No hay comandos para ejecutar\n";
	else {
                if (argc == 2) {
			cmd = argv[1];
                        if (cmd == "-stop")
				enviar("stop");
			if (cmd == "-pl")
				enviar("pl");
   			if (cmd == "-ri")
   				enviar("ri");	   
			if ((cmd!="-pl")&&(cmd!="-ri")&&(cmd!="-stop"))
                           std::cout << "No es un comando reconocido o faltan argumentos\n";
		}
		if (argc == 3) {
			cmd = argv[1];
			if (cmd == "-pa")
				procesar("pa",argv[2]);
   			if (cmd == "-pd")
   				procesar("pd",argv[2]);
   			if (cmd == "-s")
   				procesar("st",StringToLower(argv[2]));		   
			if ((cmd!="-pa")&&(cmd!="-pd")&&(cmd!= "-s"))
			   std::cout << "No es un comando reconocido o error en argumentos\n";
		}
		if (argc == 4) {
		    std::cout << "No es un comando reconocido o error en argumentos\n";
		}
		if (argc == 5) {
			cmd = argv[1];
			cmd2 = argv[3];
			if ((cmd == "-c")&&(cmd2 == "-s"))
				procesar("sc",argv[2],StringToLower(argv[4]));
		   if ((cmd == "-s")&&(cmd2 == "-c"))
				procesar("sc",argv[4],StringToLower(argv[2]));
			if ((!((cmd == "-c")&&(cmd2 == "-s")))&&(!((cmd == "-s")&&(cmd2 == "-c"))))
			   std::cout << "No es un comando reconocido\n";
		}
		if (argc > 5)
		   std::cout << "Demasiados argumentos\n";
	}
	return 0;
}
